package com.liruo.learn.spring.mvc.config.mvc;

import com.liruo.learn.spring.mvc.err.BaseResp;
import java.util.stream.Collectors;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

//@Configuration
public class ExceptionConfig implements WebMvcConfigurer {
    @ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "Resource Not Found")
    public static class ResourceNotFoundException extends RuntimeException {
        // exception implementation
        public ResourceNotFoundException(String message) {
            super(message);
        }
    }

    @RestControllerAdvice
    public static class GlobalExceptionHandler {

        public GlobalExceptionHandler() {
            System.out.println();
        }

        @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
        @ExceptionHandler(Throwable.class)
        public BaseResp<String> withStatus(Throwable e) {
            HttpStatus internalServerError = HttpStatus.INTERNAL_SERVER_ERROR;
            return BaseResp.fail(internalServerError.value(), internalServerError.getReasonPhrase() + "," + e.getMessage());
        }

        /**
         * @RequestBody 上校验失败后抛出的异常是 MethodArgumentNotValidException 异常。
         */
        @ExceptionHandler(MethodArgumentNotValidException.class)
        public String handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
            BindingResult bindingResult = e.getBindingResult();
            String messages = bindingResult.getAllErrors().stream().map(ObjectError::getDefaultMessage).collect(
                Collectors.joining(";"));
            return messages;
        }

        /**
         * 不加 @RequestBody注解，校验失败抛出的则是 BindException
         */
        @ExceptionHandler(value = BindException.class)
        public String exceptionHandler(BindException e) {
            String messages = e.getBindingResult().getAllErrors().stream().map(ObjectError::getDefaultMessage).collect(Collectors.joining(";"));
            return messages;
        }

        /**
         * @RequestParam 上校验失败后抛出的异常是 ConstraintViolationException   即校验普通参数失败
         */
        @ExceptionHandler({ConstraintViolationException.class})
        public String methodArgumentNotValid(ConstraintViolationException exception) {
            String message = exception.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining(";"));
            return message;
        }
    }

}